package com.code.services.impl;

import com.code.consts.HeaderConstants;
import com.code.daos.user.LoginCredentialMapper;
import com.code.daos.user.UserMapper;
import com.code.enums.CacheKeyEnum;
import com.code.enums.CallSourceEnum;
import com.code.enums.ResultCode;
import com.code.exceptions.BusinessException;
import com.code.helpers.LoginTokenHelper;
import com.code.helpers.PasswordHelper;
import com.code.models.login.LoginCredentialVO;
import com.code.models.user.LoginCredential;
import com.code.models.user.LoginTokenBO;
import com.code.models.user.User;
import com.code.services.LoginTokenService;
import com.code.services.UserService;
import com.code.utils.IpUtil;
import com.code.utils.RequestContextUtil;
import com.code.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 用户业务实现类
 *
 * @author xiaoyaowang
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private LoginTokenService loginTokenService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private LoginCredentialMapper loginCredentialMapper;

    @Override
    public LoginTokenBO login(LoginCredentialVO loginCredentialVO) throws Exception {
        //用户密码
        String loginPwd = loginCredentialVO.getPwd();
        if (StringUtil.isEmpty(loginPwd)) {
            throw new BusinessException(ResultCode.USER_PWD_ERROR);
        }
        String mobilePhone = loginCredentialVO.getAccount();
        //判断用户是否存在
        String userId = userMapper.getIdByPhone(mobilePhone);
        if (StringUtil.isEmpty(userId)) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        //判断用户的账号是否已经冻结（未启用）
        User user = userMapper.getUserByPhone(mobilePhone);
        String userStatus = user.getUserStatus();
        if (User.UserStatusEnum.DISABLED.name().equalsIgnoreCase(userStatus)) {
            throw new BusinessException(ResultCode.USER_ACCOUNT_FORBIDDEN);
        }

        LoginCredential loginCredentialDB = loginCredentialMapper.getLoginCredentialByPhone(mobilePhone);
        if (null == loginCredentialDB) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        String salt = loginCredentialDB.getRandomSalt();
        loginPwd = PasswordHelper.encodeBySalt(loginPwd, salt);
        String pwdForDb = loginCredentialDB.getPwd();
        log.info("通过密码登陆时的客户端加过密的密码：[{}],相关手机号：[{}] 对应的数据库的密码：[{}]", loginPwd, mobilePhone, pwdForDb);
        if (!pwdForDb.equals(loginPwd)) {
            //TODO 不正确密码则进行阈值的判断，在某一个时间段内超过一定的阈值则关闭小黑屋，嘻嘻！处理人：唐一菲 处理时间：待定
            throw new BusinessException(ResultCode.USER_PWD_ERROR);
        }
        LoginCredential loginCredential = LoginCredential.builder().account(loginCredentialDB.getAccount())
                .id(loginCredentialDB.getId()).build();
        LoginTokenBO loginToken = new LoginTokenBO();
        loginToken.setLoginCredential(loginCredential);
        loginToken.setLoginUser(user);

        loginToken.setTtl(CacheKeyEnum.VALUE_LOGIN_TOKENS.sec().longValue());
        loginToken.setIp(IpUtil.getRealIp(RequestContextUtil.getRequest()));
        String callSource = RequestContextUtil.getRequest().getHeader(HeaderConstants.CALL_SOURCE);
        loginToken.setPlatform(callSource);
        loginToken.setCreateTime(new Date());

        LoginTokenBO token = loginTokenService.add(loginToken);
        String tokenId = token.getId();
        log.info("通过密码登陆时的手机号：[{}]，对应的登陆tokenId：[{}]", mobilePhone, tokenId);
        if (CallSourceEnum.WEB.name().equals(callSource)) {
            LoginTokenHelper.addLoginTokenIdToCookie(tokenId, CacheKeyEnum.VALUE_LOGIN_TOKENS.sec());
        }
        return token;
    }

    /**
     * 退出登录
     */
    @Override
    public void logout() {
        //从缓存中移出token
        String loginTokenId = LoginTokenHelper.getLoginTokenId();
        loginTokenService.deleteById(loginTokenId);
        String callSource = RequestContextUtil.getRequest().getHeader(HeaderConstants.CALL_SOURCE);
        //如果调用来源是web端，则从cookie中删除登陆token
        if (CallSourceEnum.WEB.name().equals(callSource)) {
            //浏览器中删除token
            LoginTokenHelper.delLoginTokenIdFromCookie();
        }
    }

}
